using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

using System.Data.Odbc;
using System.Drawing;
using System.Text.RegularExpressions;
using EditWebSite.Logics;
using EditWebSite.Database;
using System.Diagnostics;
using EditWebSite.Controls;

namespace EditWebSite
{
    internal class Helper
    {
        #region ATTRIBUTES
        DatabaseHelper _Helper;
        Dictionary<string, string> _Viste;
        List<string> _Owner;
        List<string> _Tabelle;
        List<string> _Campi;
        List<string> _keywords;
        List<string> _keyCampi;
        List<string> _keyTabelle;
        List<string> _keyIntellisense;
        // prova fallita con: \bSELECT\b|\bINSERT\b|\bINTO\b|\bUPDATE\b|\bDELETE\b|\bAS\b|\bFROM\b|\bWHERE\b|\bAND\b|\bOR\b|\bIN\b|\bEXIST\b|\bCOUNT\b|\bSUM\b|\bGROUP\b|\bBY\b|\bHAVING\b|\bORDER\b|\bINNER\b|\bJOIN\b|\bLEFT\b|\bRIGHT\b|\bOUTER\b|\bSET\b
        private string keyWords = "SELECT|INSERT|INTO|UPDATE|DELETE|AS|FROM|WHERE|AND|OR|IN|EXIST|COUNT|SUM|GROUP|BY|HAVING|ORDER|INNER|JOIN|LEFT|RIGHT|OUTER|SET|ALTER|TABLE";
        private string keyCampi = "SELECT|VALUES|SET|WHERE|HAVING|GROUP|ORDER|DELETE";
        private string keyTabelle = "FROM|INTO|UPDATE|ALTER";
        private string keyIntellisense = ",|AND|OR|(";
        private Regex punteggiatura = new Regex(@"[.()=><]");
        private List<string> _TabelleMenzionate;
        private Dictionary<string, string> _Alias;
        #endregion

        #region CONST
        public Color COLOR_KEYWORD = Color.CornflowerBlue;
        public Color COLOR_OWNER = Color.DarkSlateBlue;
        public Color COLOR_VISTA = Color.LawnGreen;
        public Color COLOR_PUNTEGGIATURA = Color.Yellow;
        public Color COLOR_COMMENTI = Color.Cyan;
        public Color COLOR_STRING = Color.DarkRed;
        public Color COLOR_NORMAL = Color.White;
        public Color COLOR_CAMPI = Color.LightSalmon;
        #endregion

        #region CONSTRUCTOR
        public Helper(DatabaseHelper Helper)
        {
            _Helper = Helper;
            _Owner = new List<string>();
            _Viste = new Dictionary<string, string>();
            _Tabelle = new List<string>(GetTabelle());
            _Campi = new List<string>(GetCampi(_Tabelle.ToArray()));
            string[] kw = keyWords.Split('|');
            _keywords = new List<string>(kw);
            kw = keyCampi.Split('|');
            _keyCampi = new List<string>(kw);
            kw = keyTabelle.Split('|');
            _keyTabelle = new List<string>(kw);
            kw = keyIntellisense.Split('|');
            _keyIntellisense = new List<string>(kw);
            _Alias = new Dictionary<string, string>();
        }

        #endregion

        #region METHOD
        internal Color GetColor(string parola)
        {
            try
            {
                if (_Campi.Contains(parola))
                    return COLOR_CAMPI;
                if (_Owner.Contains(parola))
                    return COLOR_OWNER;
                if (_Tabelle.Contains(parola))
                    return COLOR_VISTA;
                if (_Viste.ContainsKey(parola))
                    return COLOR_VISTA;
                if (punteggiatura.Match(parola).Success)
                    return COLOR_PUNTEGGIATURA;
                if (_keywords.Contains(parola))
                    return COLOR_KEYWORD;
                if (_Alias.ContainsKey(parola))
                    return COLOR_VISTA;
                if (parola.StartsWith("'") && parola.EndsWith("'"))
                    return COLOR_STRING;
                return COLOR_NORMAL;

            }
            catch (Exception)
            {
                throw;
            }
        }

        internal bool ContieneParoleChiave(string testo)
        {
            if (_keyCampi.Contains(testo.Trim().ToUpper()))
                return true;
            else
                return false;
        }

        internal bool ContienePunteggiatura(string parola)
        {
            return punteggiatura.Match(parola).Success;
        }

        internal string[] Separa(string parola)
        {
            try
            {
                List<string> parole = new List<string>();
                StringBuilder temp = new StringBuilder();
                string t;
                for (int i = 0; i < parola.Length; i++)
                {
                    t = parola.Substring(i, 1);
                    if (punteggiatura.Match(t).Success)
                    {
                        if (temp.Length > 0)
                        {
                            parole.Add(temp.ToString());
                            temp = new StringBuilder();
                        }
                        parole.Add(parola.Substring(i, 1));
                    }
                    else
                        temp.Append(t);
                }
                if (temp.Length > 0)
                {
                    parole.Add(temp.ToString());
                }
                return parole.ToArray();
            }
            catch (Exception)
            {
                throw;
            }
        }

        internal Color GetColorCommento()
        {
            return COLOR_COMMENTI;
        }

        internal Color GetColorStringa()
        {
            return COLOR_STRING;
        }
        internal string[] GetTabelle()
        {
            try
            {
                Dictionary<string, Tabella> tab = _Helper.GetTabelle();

                List<string> elenco = new List<string>(tab.Keys);

                return elenco.ToArray();
            }
            catch (Exception)
            {
                #region LOGIC
                throw;
                #endregion
            }
        }

        internal string[] GetCampi(string[] tabelle)
        {
            try
            {
                Dictionary<string, Tabella> tab = _Helper.GetTabelle();
                List<string> campi = new List<string>();

                for (int i = 0; i < tabelle.Length; i++)
                {
                    Tabella t = tab[tabelle[i]];
                    for (int j = 0; j < t.Colonne.Length; j++)
                    {

                        if (!campi.Contains(t.Colonne[j].Nome))
                            campi.Add(t.Colonne[j].Nome);

                    }
                }
                if (_Alias != null)
                {
                    foreach (string alias in _Alias.Keys)
                    {
                        campi.Add(alias);
                    }
                }

                campi.Sort();
                return campi.ToArray();
            }
            catch (Exception)
            {
                #region LOGIC
#if DEBUG
                Debugger.Break();
#endif
                throw;
                #endregion
            }
        }
        internal string[] GetCampi(string tabella)
        {
            try
            {
                Dictionary<string, Tabella> tab = _Helper.GetTabelle();
                List<string> campi = new List<string>();

                Tabella t = tab[tabella];
                for (int j = 0; j < t.Colonne.Length; j++)
                {

                    if (!campi.Contains(t.Colonne[j].Nome))
                        campi.Add(t.Colonne[j].Nome);

                }

                campi.Sort();
                return campi.ToArray();
            }
            catch (Exception)
            {
                #region LOGIC
#if DEBUG
                Debugger.Break();
#endif
                throw;
                #endregion
            }
        }
        internal string[] GetCampi()
        {
            try
            {
                return GetCampi(_TabelleMenzionate.ToArray());
            }
            catch (Exception)
            {
                #region LOGIC
#if DEBUG
                Debugger.Break();
#endif
                throw;
                #endregion
            }
        }

        internal SyntaxText.TipoVisualizzazioni GetTipoVisualizzazione(string Testo, int Posizione)
        {
            try
            {
                SyntaxText.TipoVisualizzazioni tipo = SyntaxText.TipoVisualizzazioni.Nulla;

                string testo = Testo.Substring(0, Posizione);
                string[] parole = Regex.Split(testo, "[\r\n ]");

                _TabelleMenzionate = new List<string>();
                _Alias = new Dictionary<string, string>();

                for (int i = parole.Length - 1; i > -1; i--)
                {
                    if (_keyCampi.Contains(parole[i]))
                    {
                        tipo = SyntaxText.TipoVisualizzazioni.Campi;
                        break;
                    }
                    if (_keyTabelle.Contains(parole[i]))
                    {
                        tipo = SyntaxText.TipoVisualizzazioni.Tabelle;
                        break;
                    }
                    if (_Alias.ContainsKey(parole[i]))
                    {
                        tipo = SyntaxText.TipoVisualizzazioni.Campi;
                        break;
                    }
                }
                if (tipo == SyntaxText.TipoVisualizzazioni.Campi)
                {
                    parole = Regex.Split(Testo, "[\r\n ]");
                    for (int i = parole.Length - 1; i > -1; i--)
                    {
                        if (_Tabelle.Contains(parole[i]) && !_TabelleMenzionate.Contains(parole[i]))
                        {
                            _TabelleMenzionate.Add(parole[i]);
                            if (i + 1 < parole.Length && !parole[i + 1].Equals("AS"))
                            {
                                if (!_keywords.Contains(parole[i + 1]) && !punteggiatura.Match(parole[i + 1]).Success)
                                {
                                    if (!_Alias.ContainsKey(parole[i + 1]))
                                    {
                                        _Alias.Add(parole[i + 1], parole[i]);
                                    }
                                }
                            }
                            else if (i + 2 < parole.Length)
                            {
                                if (!_keywords.Contains(parole[i + 2]) && !punteggiatura.Match(parole[i + 2]).Success)
                                {
                                    if (!_Alias.ContainsKey(parole[i + 2]))
                                    {
                                        _Alias.Add(parole[i + 2], parole[i]);
                                    }
                                }

                            }
                        }
                    }
                }

                if (tipo == SyntaxText.TipoVisualizzazioni.Campi && _TabelleMenzionate.Count == 0)
                    return SyntaxText.TipoVisualizzazioni.Nulla;
                return tipo;
            }
            catch (Exception)
            {
                #region LOGIC
#if DEBUG
                Debugger.Break();
#endif
                throw;
                #endregion
            }
        }

        internal bool IsIntellisenseDaVisualizzare(string linea)
        {
            try
            {
                string line = linea.Trim();
                string[] parole = linea.Split(' ');
                if (parole.Length > 0)
                {
                    int indice = parole.Length - 1;
                    while (indice > 0)
                    {
                        if (parole[indice].Equals(string.Empty))
                            indice--;
                        else
                            break;
                    }
                    if (indice > -1)
                    {
                        if (_keyIntellisense.Contains(parole[indice]) || parole[indice].EndsWith(","))
                            return true;
                        return _keywords.Contains(linea.Trim().ToUpper());
                    }
                }
                return false;

            }
            catch (Exception)
            {
                #region LOGIC
                throw;
                #endregion
            }
        }

        internal string[] GetCampiTabellaPrecedente(string Testo, int Posizione)
        {
            try
            {
                string testo = Testo.Substring(0, Posizione);
                string[] parole = Regex.Split(testo, "[\r\n ]");
                int i = parole.Length - 1;
                while (parole[i].Equals(string.Empty))
                {
                    i--;
                }
                string nome = parole[i].ToUpper();
                if (nome.EndsWith("."))
                    nome = nome.Substring(0, nome.Length - 1);

                // controllo che non ci siano schifezze all'inizio
                if (nome.Trim().Length > 2 && (punteggiatura.Match(nome.Trim().Substring(0, 1)).Success || nome.Trim().Substring(0,1).Equals(",")))
                {
                    nome = nome.Trim().Substring(1, nome.Trim().Length-1);
                }

                if (_TabelleMenzionate.Contains(nome))
                {
                    return GetCampi(nome);
                }
                else if (_Alias.ContainsKey(nome))
                {
                    return GetCampi(_Alias[nome]);
                }
                return new string[] { };
            }
            catch (Exception)
            {
                #region LOGIC
#if DEBUG
                Debugger.Break();
#endif
                throw;
                #endregion
            }
        }
        #endregion
    }
}
